﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test.UI.OpenGL.Animations;

/// <summary>
/// 振型数据，包含某个频率下所有测量点的振型信息
/// </summary>
/// <param name="frequency"> 频率（Hz）</param>
/// <param name="name">振型名称</param>
public class ModalData(float frequency, string name = "")
{
    /// <summary>
    /// 频率（Hz）
    /// </summary>
    public float Frequency { get; set; } = frequency;

    /// <summary>
    /// 振型名称
    /// </summary>
    public string Name { get; set; } = string.IsNullOrEmpty(name) ? $"Mode_{frequency:F2}Hz" : name;

    /// <summary>
    /// 振型数据点列表
    /// </summary>
    public List<ModalPoint> Points { get; set; } = [];

    /// <summary>
    /// 最大幅值（用于归一化）
    /// </summary>
    public float MaxAmplitude { get; private set; } = 0.0f;

    /// <summary>
    /// 添加振型数据点
    /// </summary>
    /// <param name="point">振型数据点</param>
    public void AddPoint(ModalPoint point)
    {
        Points.Add(point);
        UpdateMaxAmplitude(point);
    }

    /// <summary>
    /// 批量添加振型数据点
    /// </summary>
    /// <param name="points">振型数据点数组</param>
    public void AddPoints(ModalPoint[] points)
    {
        Points.AddRange(points);
        foreach (var point in points)
        {
            UpdateMaxAmplitude(point);
        }
    }

    /// <summary>
    /// 从幅值和相位数组创建振型数据
    /// </summary>
    /// <param name="amplitudesX">X方向幅值数组</param>
    /// <param name="amplitudesY">Y方向幅值数组</param>
    /// <param name="amplitudesZ">Z方向幅值数组</param>
    /// <param name="phasesX">X方向相位数组（弧度）</param>
    /// <param name="phasesY">Y方向相位数组（弧度）</param>
    /// <param name="phasesZ">Z方向相位数组（弧度）</param>
    public void SetFromArrays(float[] amplitudesX, float[] amplitudesY, float[] amplitudesZ,
                             float[] phasesX, float[] phasesY, float[] phasesZ)
    {
        // 检查所有输入数组长度是否一致
        if (amplitudesX.Length != amplitudesY.Length || amplitudesY.Length != amplitudesZ.Length ||
            amplitudesZ.Length != phasesX.Length || phasesX.Length != phasesY.Length ||
            phasesY.Length != phasesZ.Length)
        {
            throw new ArgumentException("所有数组的长度必须相同");
        }

        Points.Clear();
        MaxAmplitude = 0.0f;

        // 构造并添加每个振型数据点
        for (int i = 0; i < amplitudesX.Length; i++)
        {
            var point = new ModalPoint(
                amplitudesX[i], amplitudesY[i], amplitudesZ[i],
                phasesX[i], phasesY[i], phasesZ[i],
                i
            );
            AddPoint(point);
        }
    }

    /// <summary>
    /// 更新最大幅值
    /// </summary>
    /// <param name="point">振型数据点</param>
    private void UpdateMaxAmplitude(ModalPoint point)
    {
        // 计算当前点在三个方向上的最大幅值绝对值
        float maxAmp = MathF.Max(MathF.Max(MathF.Abs(point.AmplitudeX), MathF.Abs(point.AmplitudeY)), MathF.Abs(point.AmplitudeZ));
        if (maxAmp > MaxAmplitude)
        {
            MaxAmplitude = maxAmp;
        }
    }

    /// <summary>
    /// 获取归一化的振型数据点
    /// </summary>
    /// <param name="index">点索引</param>
    /// <returns>归一化的振型数据点</returns>
    public ModalPoint GetNormalizedPoint(int index)
    {
        // 检查索引有效性及最大幅值是否为零
        if (index < 0 || index >= Points.Count || MaxAmplitude == 0.0f)
        {
            return new ModalPoint();
        }

        var point = Points[index];
        // 对幅值进行归一化处理
        return new ModalPoint(
            point.AmplitudeX / MaxAmplitude,
            point.AmplitudeY / MaxAmplitude,
            point.AmplitudeZ / MaxAmplitude,
            point.PhaseX,
            point.PhaseY,
            point.PhaseZ,
            point.VertexIndex
        );
    }
}